package ${packageName};

<#list jedisImports as imports>
import ${imports};
</#list>
/**
 * ${tableName}
 * 1.做为Jedis单独使用的情况，我是不建议的!他不能保证线程安全性问题，没有数据补救的操作
 * 2.jedis的查询数据是没有顺序的
 */
public class ${d_tableName}Jedis{
	static class ${d_tableName}Sore implements Comparator<${d_tableName}> {
		@Override
		public int compare(${d_tableName} ${x_tableName}1, ${d_tableName} ${x_tableName}2) {
			if (${x_tableName}1.get${primaryD_columnName}() > ${x_tableName}2.get${primaryD_columnName}())
				return 1;
			else if (${x_tableName}1.get${primaryD_columnName}() < ${x_tableName}2.get${primaryD_columnName}())
				return -1;
			else {
				return 0;
			}
		}
	}
	//表锁(重入锁)
	static final ReentrantLock tableLock = new ReentrantLock();
	
	static Comparator<${d_tableName}> comparator = new ${d_tableName}Sore();
	
	<#list indexKeys as index>
	/**
	 * 根据(<#list index.columnNames as columnName> ${columnName} </#list>) 查询
	 */
	<#if index.unique>
	<#-- 唯一索引查询 -->
	public static ${d_tableName} getBy<#list index.d_columnNames as d_columnName>${d_columnName}</#list>(${index.all_basicType_x_columnName}){
		Jedis jedis = SK_Config.getJedisPoll().getResource();
		${d_tableName} ${x_tableName} = null;
		try{
		<#if index.indexName == "PRIMARY">
			String key = "${d_tableName}_Object";
			String field = SK_Plus.b("${index.all_x_columnName}:",${index.all_x_columnName}).e();
			String json = jedis.hget(key,field);
			if(!SK_String.isEmpty(json))
				${x_tableName} = ${d_tableName}.createForJson(json);
		<#else>
			String key = "${d_tableName}_Index";
			String field = SK_Plus.b("${index.all_x_columnName}:",${index.all_x_columnName_}).e();
			String primaryKey = jedis.hget(key,field);
			if(primaryKey!=null){
				${x_tableName} = getBy${primaryD_columnName}(Integer.valueOf(primaryKey));
			}
		</#if>
		}finally{
			 SK_Config.getJedisPoll().returnResource(jedis);
		}
		return ${x_tableName};
	}
	
	<#if index.indexName == "PRIMARY">
	public static List<${d_tableName}> getBy<#list index.d_columnNames as d_columnName>${d_columnName}</#list>In(${index.all_basicType_x_columnNames}){
		Jedis jedis = SK_Config.getJedisPoll().getResource();
		List<${d_tableName}> ${x_tableName}s = new ArrayList<${d_tableName}>();
		try{
			String key = "${d_tableName}_Object";
			String[] strIds = new String[ids.length];
			for (int i = 0; i < strIds.length; i++) {
				strIds[i] = String.valueOf(ids[i]);
			}
			List<String> jsons = jedis.hmget(key,strIds);
			 ${x_tableName}s = ${d_tableName}.createForJson(jsons);
		}catch (Exception e) {
			
		}finally{
			 SK_Config.getJedisPoll().returnResource(jedis);
		}
		return ${x_tableName}s;
	}
	</#if>
	<#else>
	<#-- 聚集索引查询 -->
	public static List<${d_tableName}> getBy<#list index.d_columnNames as d_columnName>${d_columnName}</#list>(${index.all_basicType_x_columnName}){
		Jedis jedis = SK_Config.getJedisPoll().getResource();
		List<${d_tableName}> ${x_tableName}s = new ArrayList<${d_tableName}>();
		try{
			String key = "${d_tableName}_Index";
			String field = SK_Plus.b(key,"${index.all_x_columnName}:",${index.all_x_columnName_}).e();
			Set<String> setStr = jedis.smembers(field);
			if(setStr!=null){
				key = "${d_tableName}_Object";
				String[] fieldArray = (String[]) setStr.toArray();
				List<String> jsons = jedis.hmget(key,fieldArray);
				${x_tableName}s = ${d_tableName}.createForJson(jsons);
			}
		}finally{
			 SK_Config.getJedisPoll().returnResource(jedis);
		}
		Collections.sort(${x_tableName}s, comparator);
		return ${x_tableName}s;
	}
	
	
	public static List<${d_tableName}> getByPage<#list index.d_columnNames as d_columnName>${d_columnName}</#list>(${index.all_basicType_x_columnName},int page,int size,SK_PageCount pageCount){
		List<${d_tableName}> ${x_tableName}s = getBy<#list index.d_columnNames as d_columnName>${d_columnName}</#list>(${index.all_x_columnName});
		${x_tableName}s = SK_List.getPage(${x_tableName}s, page, size, pageCount);
		return ${x_tableName}s;
	}
	
	</#if>
	</#list>

	public static List<${d_tableName}> getAll(){
		Jedis jedis = SK_Config.getJedisPoll().getResource();
		List<${d_tableName}> ${x_tableName}s = new ArrayList<${d_tableName}>();
		try{
			String key = "${d_tableName}_Object";
			List<String> jsons = jedis.hvals(key);
			${x_tableName}s = ${d_tableName}.createForJson(jsons);
		}finally{
			 SK_Config.getJedisPoll().returnResource(jedis);
		}
		Collections.sort(${x_tableName}s, comparator);
		return ${x_tableName}s;
	}
	
	
	public static List<${d_tableName}> getAllByPage(int page,int size,SK_PageCount pageCount){
		List<${d_tableName}> ${x_tableName}s = getAll();
		${x_tableName}s = SK_List.getPage(${x_tableName}s, page, size, pageCount);
		return ${x_tableName}s;
	}
	
	
	public static ${d_tableName} putData(${d_tableName} ${x_tableName},Pipeline p,int type) throws SK_Exception{
		boolean isLock = (type == SK_Config.CHECK_ALL_INDEX);
		Map<String,String> updateIndexs = null;
		if(type == SK_Config.CHECK_UPDATE_INDEX){
			updateIndexs = ${x_tableName}.getUpdateIndexs();
			isLock = updateIndexs.containsKey("isUpdtaeUnique");
		}
		try{
			DbLock.lock(${x_tableName}.get${primaryD_columnName}(),DbLock.${x_tableName}_locks);
			if(isLock)tableLock.lock();
			switch (type) {
			case SK_Config.CHECK_ALL_INDEX:
				checkUniqueIndex(${x_tableName});
				break;
			case SK_Config.CHECK_UPDATE_INDEX:
				checkUniqueIndex(updateIndexs);
				break;
			}
			if(type == SK_Config.CHECK_UPDATE_INDEX){
				removeData(${x_tableName});
			}
			<#assign i=0 />
			<#assign u=0 />
			<#assign k=0 />
			<#list indexKeys as index>
			<#if index.unique>
			<#if index.indexName == "PRIMARY">
			// ---------------------- 主键索引 ----------------------
			String key = "${d_tableName}_Object";
			String field = SK_Plus.b("${index.all_x_columnName}:",${index.all_x_columnName_get}).e();
			String data = ${x_tableName}.toJson();
			p.hset(key,field,data);
			
			<#else>
			<#if i==0>
			// ---------------------- 唯一索引 ----------------------
			String primaryKey = String.valueOf(${x_tableName}.get${primaryD_columnName}());
			key = "${d_tableName}_Index";
			
			<#assign i=1 />
			</#if>
			field = SK_Plus.b("${index.all_x_columnName}:",${index.all_x_columnName_get}).e();
			p.hset(key,field,primaryKey);
			
			</#if>
			<#else>
			<#if i==0>
			String primaryKey = String.valueOf(${x_tableName}.get${primaryD_columnName}());
			key = "${d_tableName}_Index";
			<#assign i=1 />
			</#if>
			<#if u==0>
			// ---------------------- 聚集索引 ----------------------
			<#assign u=1 />
			</#if>
			field = SK_Plus.b(key,"${index.all_x_columnName}:",${index.all_x_columnName_get}).e();
			p.sadd(field, primaryKey);
			
			</#if>
			</#list>
		}finally{
			 DbLock.unlock(${x_tableName}.get${primaryD_columnName}(),DbLock.${x_tableName}_locks);
			 if(isLock)tableLock.unlock();
		}
		return ${x_tableName};
	}
	
	public static List<${d_tableName}> putDataAll(List<${d_tableName}> ${x_tableName}s,int type){
		Jedis jedis = SK_Config.getJedisPoll().getResource();
		List<${d_tableName}> ${x_tableName}s_ = new ArrayList<${d_tableName}>();
		try{
			Pipeline p = jedis.pipelined();
			for(${d_tableName} ${x_tableName} : ${x_tableName}s){
				try {
					${x_tableName}s_.add(putData(${x_tableName},p,type));
				} catch (SK_Exception e) {
					e.printStackTrace();
				}
			}
			p.sync();
		}finally{
			 SK_Config.getJedisPoll().returnResource(jedis);
		}
		return ${x_tableName}s_;
	}
	
	public static void removeData(${d_tableName} ${x_tableName}){
		Jedis jedis = SK_Config.getJedisPoll().getResource();
		try{
			Pipeline p = jedis.pipelined();
			removeData(${x_tableName},p);
			p.sync();
		}finally{
			 SK_Config.getJedisPoll().returnResource(jedis);
		}
	}
	
	/**
	 * 清空一个缓存
	 */
	public static void removeData(${d_tableName} ${x_tableName},Pipeline p){
		try{
			DbLock.lock(${x_tableName}.get${primaryD_columnName}(),DbLock.${x_tableName}_locks);
			<#assign i=0 />
			<#assign u=0 />
			<#list indexKeys as index>
			<#if index.unique>
			<#if index.indexName == "PRIMARY">
			// ---------------------- 主键索引 ----------------------
			String key = "${d_tableName}_Object";
			String field = SK_Plus.b("${index.all_x_columnName}:",${x_tableName}.get<#list index.d_columnNames as d_columnName>${d_columnName}</#list>_Unique()).e();
			p.hdel(key,field);
			
			<#else>
			<#if i==0>
			// ---------------------- 唯一索引 ----------------------
			key = "${d_tableName}_Index";
			
			<#assign i=1 />
			</#if>
			field = SK_Plus.b("${index.all_x_columnName}:",${x_tableName}.get<#list index.d_columnNames as d_columnName>${d_columnName}</#list>_Unique()).e();
			if(field!=null){
				p.hdel(key,field);
			}
			</#if>
			<#else>
			<#if i==0>
			key = "${d_tableName}_Index";
			<#assign i=1 />
			</#if>
			<#if u==0>
			// ---------------------- 聚集索引 ----------------------
			String primaryKey = String.valueOf(${x_tableName}.get${primaryD_columnName}());
			<#assign u=1 />
			</#if>
			field = SK_Plus.b(key,"${index.all_x_columnName}:",${x_tableName}.get<#list index.d_columnNames as d_columnName>${d_columnName}</#list>_Index()).e();
			p.srem(field, primaryKey);
			
			</#if>
			</#list>
		}finally{
			 DbLock.unlock(${x_tableName}.get${primaryD_columnName}(),DbLock.${x_tableName}_locks);
		}
	}

	public static void removeDataAll(List<${d_tableName}> ${x_tableName}s){
		Jedis jedis = SK_Config.getJedisPoll().getResource();
		try{
			Pipeline p = jedis.pipelined();
			for(${d_tableName} ${x_tableName} : ${x_tableName}s){
				removeData(${x_tableName},p);
			}
			p.sync();
		}finally{
			 SK_Config.getJedisPoll().returnResource(jedis);
		}
	}
	
	public static ${d_tableName} insert(${d_tableName} ${x_tableName}){
		Jedis jedis = SK_Config.getJedisPoll().getResource();
		Jedis jedisPipeline = SK_Config.getJedisPoll().getResource();
		Pipeline p = jedisPipeline.pipelined();
		try{
			if(${x_tableName}.get${primaryD_columnName}() < 1){
				try {
					tableLock.lock();
					${x_tableName}.set${primaryD_columnName}(jedis.hincrBy("primaryKey", ${d_tableName}.CLASS_NAME,1).intValue());
				}finally{
					tableLock.unlock();
				}
			}
			DbLock.lock(${x_tableName}.get${primaryD_columnName}(),DbLock.${x_tableName}_locks);
			try {
				${x_tableName} = putData(${x_tableName}, p, SK_Config.CHECK_ALL_INDEX);
				p.sync();
				return ${x_tableName};
			} catch (SK_Exception e) {
				e.printStackTrace();
			}
    	}finally{
			 SK_Config.getJedisPoll().returnResource(jedis);
			 SK_Config.getJedisPoll().returnResource(jedisPipeline);
			 DbLock.unlock(${x_tableName}.get${primaryD_columnName}(),DbLock.${x_tableName}_locks);
		}
		return null;
    }
    
    public static List<${d_tableName}> insertBatch(List<${d_tableName}> ${x_tableName}s){
    	Jedis jedis = SK_Config.getJedisPoll().getResource();
    	try{
			${x_tableName}s = putDataAll(${x_tableName}s, SK_Config.CHECK_ALL_INDEX);
			jedis.hincrBy("primaryKey", ${d_tableName}.CLASS_NAME,${x_tableName}s.size());
		}finally{
			 SK_Config.getJedisPoll().returnResource(jedis);
		}
    	return ${x_tableName}s;
    }
    
    public static ${d_tableName} update(${d_tableName} ${x_tableName}){
    	Jedis jedis = SK_Config.getJedisPoll().getResource();
		Jedis jedisPipeline = SK_Config.getJedisPoll().getResource();
		Pipeline p = jedisPipeline.pipelined();
		try{
			DbLock.lock(${x_tableName}.get${primaryD_columnName}(),DbLock.${x_tableName}_locks);
			try{
				${x_tableName} = putData(${x_tableName},p,SK_Config.CHECK_UPDATE_INDEX);
				p.sync();
				return ${x_tableName};
			} catch (SK_Exception e) {
				e.printStackTrace();
			}
    	}finally{
			 SK_Config.getJedisPoll().returnResource(jedis);
			 SK_Config.getJedisPoll().returnResource(jedisPipeline);
			 DbLock.unlock(${x_tableName}.get${primaryD_columnName}(),DbLock.${x_tableName}_locks);
		}
		return null;
    }
    
    public static List<${d_tableName}> updateBatch(List<${d_tableName}> ${x_tableName}s){
    	removeDataAll(${x_tableName}s);
		putDataAll(${x_tableName}s,SK_Config.CHECK_UPDATE_INDEX);
    	return ${x_tableName}s;
    }
    
    public static boolean delete(${d_tableName} ${x_tableName}){
    	Jedis jedis = SK_Config.getJedisPoll().getResource();
		Jedis jedisPipeline = SK_Config.getJedisPoll().getResource();
		Pipeline p = jedisPipeline.pipelined();
		boolean bool = true;
		try{
			DbLock.lock(${x_tableName}.get${primaryD_columnName}(),DbLock.${x_tableName}_locks);
	    	removeData(${x_tableName},p);
	    	p.sync();
	    }finally{
			 SK_Config.getJedisPoll().returnResource(jedis);
			 SK_Config.getJedisPoll().returnResource(jedisPipeline);
			 DbLock.unlock(${x_tableName}.get${primaryD_columnName}(),DbLock.${x_tableName}_locks);
		}
	    return bool;
    }
    
    public static boolean deleteBatch(List<${d_tableName}> ${x_tableName}s){
    	boolean bool = true;
    	removeDataAll(${x_tableName}s);
    	return bool;
    }
    
    
    
    //检查唯一索引
	private static void checkUniqueIndex(${d_tableName} ${x_tableName}) throws SK_Exception{
		Jedis jedis = SK_Config.getJedisPoll().getResource();
		try{
			tableLock.lock();
			<#assign i=0 />
			<#list indexKeys as index>
			<#if index.unique>
			<#if index.indexName == "PRIMARY">
			<#if i==0>
			<#assign i=1 />
			String key = "${d_tableName}_Object";
			String field = SK_Plus.b("${index.all_x_columnName}:",${index.all_d_columnName_get}).e();
			<#else>
			key = "${d_tableName}_Object";
			field = SK_Plus.b("${index.all_x_columnName}:",${index.all_d_columnName_get}).e();
			</#if>
			<#else>
			<#if i==0>
			<#assign i=1 />
			String key = "${d_tableName}_Object";
			String field = SK_Plus.b("${index.all_x_columnName}:",${index.all_d_columnName_get}).e();
			<#else>
			key = "${d_tableName}_Index";
			field = SK_Plus.b("${index.all_x_columnName}:",${index.all_d_columnName_get}).e();
			</#if>
			</#if>
			if(jedis.hexists(key,field))
				throw new SK_Exception(SK_ErrorCode.UNIQUE_INDEX_ERROR,SK_Plus.b(${d_tableName}.<#list index.d_columnNames as d_columnName>${d_columnName}</#list>_IndexName,"=",field).e());
				
			</#if>
			</#list>
		}finally{
			SK_Config.getJedisPoll().returnResource(jedis);
			tableLock.unlock();
		}
	}
	
	/** 检查(改变的)唯一索引 */
	private static void checkUniqueIndex(Map<String,String> indexs) throws SK_Exception{
		Jedis jedis = SK_Config.getJedisPoll().getResource();
		try{
			tableLock.lock();
			String key = "";
			for (Map.Entry<String, String> index : indexs.entrySet()) {
				switch (index.getKey()) {
				<#list indexKeys as index>
				<#if index.unique>
				case ${d_tableName}.<#list index.d_columnNames as d_columnName>${d_columnName}</#list>_IndexName:
					<#if index.indexName == "PRIMARY">
					key = "${d_tableName}_Object";
					<#else>
					key = "${d_tableName}_Index";
					</#if>
					if(jedis.hexists(key,SK_Plus.b("${index.all_x_columnName}:",index.getValue()).e()))
						throw new SK_Exception(SK_ErrorCode.UNIQUE_INDEX_ERROR,SK_Plus.b(${d_tableName}.<#list index.d_columnNames as d_columnName>${d_columnName}</#list>_IndexName,"=",index.getValue()).e());
					break;
				</#if>			
				</#list>
				}
			}
		}finally{
			SK_Config.getJedisPoll().returnResource(jedis);
			tableLock.unlock();
		}
	}
}